package com.safe.first.infrastructure.resolver;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.safe.first.common.constants.LoginEnum;
import com.safe.first.common.exception.BizException;
import com.safe.first.domain.user.User;
import com.safe.first.infrastructure.annotation.LoginUser;
import com.safe.first.infrastructure.context.BaseContextHandler;
import com.safe.first.domain.user.DefaultUser;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import java.io.IOException;
import java.util.Objects;
import java.util.Optional;

/**
 * Token转化SysUser
 */
@Slf4j
@AllArgsConstructor
public class ContextArgumentResolver implements HandlerMethodArgumentResolver {

    private final ObjectMapper objectMapper;

    /**
     * 入参筛选
     *
     * @param mp 参数集合
     * @return 格式化后的参数
     */
    @Override
    public boolean supportsParameter(MethodParameter mp) {
        return mp.getParameterType().equals(User.class);
    }

    /**
     * @param methodParameter       入参集合
     * @param modelAndViewContainer model 和 view
     * @param nativeWebRequest      web相关
     * @param webDataBinderFactory  入参解析
     * @return 包装对象
     */
    @Override
    public Object resolveArgument(MethodParameter methodParameter,
                                  ModelAndViewContainer modelAndViewContainer,
                                  NativeWebRequest nativeWebRequest,
                                  WebDataBinderFactory webDataBinderFactory) throws IOException {
        Long userId = BaseContextHandler.getUserId();
        DefaultUser user = new DefaultUser();
        user.setId(userId);
        LoginUser parameterAnnotation = methodParameter.getParameterAnnotation(LoginUser.class);
        if (Objects.nonNull(parameterAnnotation)) {
            if (Objects.requireNonNull(parameterAnnotation).isForceLogin() && Objects.isNull(user)) {
                throw new BizException(LoginEnum.NOT_LOG_IN);
            }
        } else {
            if (Objects.isNull(user)) {
                throw new BizException(LoginEnum.NOT_LOG_IN);
            }
        }



        Optional.ofNullable(methodParameter.getParameterAnnotation(LoginUser.class))
                .ifPresent(loginUser -> this.handlerLoginUser(loginUser, user));

        if (Objects.nonNull(parameterAnnotation) && Objects.isNull(user)) {
            boolean forceLogin = parameterAnnotation.isForceLogin();
            if (!forceLogin) {
                return new DefaultUser();
            }
        }

        return user;
    }

    public void handlerLoginUser(LoginUser loginUser, DefaultUser user) {

    }
}
